package com.campus.secondhand.config;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.ReadingConverter;
import org.springframework.data.convert.WritingConverter;
import org.springframework.data.elasticsearch.client.ClientConfiguration;
import org.springframework.data.elasticsearch.client.elc.ElasticsearchConfiguration;
import org.springframework.data.elasticsearch.config.ElasticsearchConfigurationSupport;
import org.springframework.data.elasticsearch.core.convert.ElasticsearchCustomConversions;
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;

import java.util.Arrays;

/**
 * ElasticSearch配置类
 */
@Configuration
@EnableElasticsearchRepositories(basePackages = "com.campus.secondhand.repository.es")
public class ElasticSearchConfig extends ElasticsearchConfiguration {

    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ISO_DATE_TIME;

    @Override
    public ClientConfiguration clientConfiguration() {
        return ClientConfiguration.builder()
                .connectedTo("localhost:9200")
                .build();
    }

    /**
     * 自定义类型转换器
     */
    @Bean
    @Override
    public ElasticsearchCustomConversions elasticsearchCustomConversions() {
        return new ElasticsearchCustomConversions(
                Arrays.asList(
                        new LocalDateTimeToStringConverter(),
                        new StringToLocalDateTimeConverter(),
                        new LongToLocalDateTimeConverter(),
                        new LocalDateTimeToLongConverter()));
    }

    /**
     * LocalDateTime转String写入转换器
     */
    @WritingConverter
    static class LocalDateTimeToStringConverter implements Converter<LocalDateTime, String> {
        @Override
        public String convert(LocalDateTime source) {
            return source != null ? source.format(DATE_TIME_FORMATTER) : null;
        }
    }

    /**
     * String转LocalDateTime读取转换器
     */
    @ReadingConverter
    static class StringToLocalDateTimeConverter implements Converter<String, LocalDateTime> {
        @Override
        public LocalDateTime convert(String source) {
            return source != null ? LocalDateTime.parse(source, DATE_TIME_FORMATTER) : null;
        }
    }

    /**
     * Long(毫秒时间戳)转LocalDateTime读取转换器
     */
    @ReadingConverter
    static class LongToLocalDateTimeConverter implements Converter<Long, LocalDateTime> {
        @Override
        public LocalDateTime convert(Long source) {
            return source != null ? LocalDateTime.ofInstant(Instant.ofEpochMilli(source), ZoneId.systemDefault())
                    : null;
        }
    }

    /**
     * LocalDateTime转Long(毫秒时间戳)写入转换器
     */
    @WritingConverter
    static class LocalDateTimeToLongConverter implements Converter<LocalDateTime, Long> {
        @Override
        public Long convert(LocalDateTime source) {
            return source != null ? source.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() : null;
        }
    }
}